﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tools.Domain.Common.ConstraintSets;
using Tools.Domain.Common.Repositories.Contracts;
using Tools.Domain.Specifications.Constraints;
using Web.App.Infrastructure.ApplicationMessages.Contracts;
using Web.App.Infrastructure.CrossCuttingConcerns.Attributes;
using Webshop20.Domain.Common.Exceptions;
using Webshop20.Domain.Customers.Core;

namespace Webshop20.Application.Operations.Messages
{
    //ToDo: UpdateAccountService
    public interface IUpdateCustomerService : IService
    {
        [Transaction]
        new ISystemMessage Handle(ISystemMessage request);
    }

    public class UpdateCustomerService : ServiceBase,IUpdateCustomerService
    {
        private readonly IRepository<Customer> customerRepository;
        private IConstraintSetFactory constraintSetFactory;

        public UpdateCustomerService(IRepository<Customer> customerRepository, IConstraintSetFactory constraintSetFactory)
        {
            this.customerRepository = customerRepository;
            this.constraintSetFactory = constraintSetFactory;
        }

        //ToDo: DomainException-Handling
        public ISystemMessage Handle(ISystemMessage request)
        {
            var customerRequest = (UpdateCustomerRequest) request;
            try
            {
                var customer = customerRepository.FindById(customerRequest.CustomerId);
                var constraintSet = constraintSetFactory.Create<IConstraintSet<Customer>>(new ExecuteAlways());
                customer.SetCustomerData(
                                            customerRequest.FirstName,
                                            customerRequest.LastName,
                                            customerRequest.EMail,
                                            customerRequest.Street,
                                            customerRequest.PostalCode,
                                            customerRequest.City,
                                            customerRequest.Country,
                                            customerRequest.PayingMethod,
                                            customerRequest.PayingMethodData,
                                            constraintSet
                                        );
                customerRepository.Update(customer);
                return new UpdateCustomerResponse(WITHOUT_DOMAIN_MESSAGE);
            }
            catch (DomainException ex)
            {
                return new UpdateCustomerResponse(ex.DomainMessage);
            }
        }
    }

    public class UpdateCustomerRequest : MessageBase
    {
        private readonly int customerId;
        private readonly string firstName;
        private readonly string lastName;
        private readonly string street;
        private readonly string postalCode;
        private readonly string city;
        private readonly string country;
        private readonly string eMail;
        private readonly string payingMethod;
        private readonly object [] payingMethodData;

        public UpdateCustomerRequest(int customerId, string firstName, string lastName, string street, string postalCode, string city, string country, string eMail, string payingMethod, object [] payingMethodData)
        {
            this.customerId = customerId;
            this.payingMethodData = payingMethodData;
            this.payingMethod = payingMethod;
            this.eMail = eMail;
            this.country = country;
            this.city = city;
            this.postalCode = postalCode;
            this.street = street;
            this.lastName = lastName;
            this.firstName = firstName;
        }

        public object[] PayingMethodData
        {
            get { return payingMethodData; }
        }

        public string PayingMethod
        {
            get { return payingMethod; }
        }

        public string EMail
        {
            get { return eMail; }
        }

        public string Country
        {
            get { return country; }
        }

        public string City
        {
            get { return city; }
        }

        public string PostalCode
        {
            get { return postalCode; }
        }

        public string Street
        {
            get { return street; }
        }

        public string LastName
        {
            get { return lastName; }
        }

        public string FirstName
        {
            get { return firstName; }
        }

        public int CustomerId
        {
            get { return customerId; }
        }
    }

    public class UpdateCustomerResponse : ResponseMessageBase
    {
        public UpdateCustomerResponse(IDomainMessage domainMessage) : base(domainMessage)
        {
        }
    }
}
